﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using App.Core.Domain;
using App.Core.Domain.BaseObject;
using App.Core.Dtos;
using App.Core.DataAccess;
using App.Core.Helpers;
using Omu.ValueInjecter;
using System.Data.Entity;
using App.Core;
using EntityFramework.Extensions;

namespace App.Services.Impls
{
    public partial class SystemServiceImpl : AppServiceBase,ISystemService
    {
        public async Task<OperationResult<MenuPermission>> CreateMenu(MenuPermissionDto dto)
        {
            using (var db = new Db() )
            {
                if (await db.MenuPermission.CountAsync(m => m.MenuText == dto.MenuText) > 0)
                {
                    return new OperationResult<MenuPermission>() { success = false, message = string.Format("名为【{0}】的菜单已经存在！", dto.MenuText) };
                }

                var menu = new MenuPermission();
                menu.InjectFrom(dto);
                menu.AutoCreated = false;

                db.MenuPermission.Add(menu);
                await db.SaveChangesAsync();

                return new OperationResult<MenuPermission>() { success = true };
            }
        }

        public async Task<OperationResult> UpdateMenu(Guid id, MenuPermissionDto dto)
        {
            using (var db = new Db())
            {
                var menu = await db.MenuPermission.FindAsync(id);
                if (menu == null)
                {
                    return new OperationResult() { success = false, message = "Not found!" };
                }

                menu.InjectFrom(dto);

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public List<Button> GetAllButton()
        {
            using (var db = new Db())
            {
                return db.Button.ToList();
            }
        }

        public List<Role> GetAllRole()
        {
            using (var db = new Db())
            {
                return db.Role.OrderBy(s=>s.CreationTime).ToList();
            }
        }

        public async Task<OperationResult<Button>> SaveButtons(BulkDto<ButtonDto> bulks)
        {
            using (var db = new Db()) {
                var curUser = new CurrentSession();
                var exists = new List<string>();
                //批量插入
                foreach (var row in bulks.InsertedRows)
                {
                    if (await db.Button.CountAsync(b => b.ButtonName == row.ButtonName || b.ButtonLink == row.ButtonLink) > 0)
                    {
                        exists.Add(string.Format("名为【{0}】的按钮或方法为【{1}】的按钮已经存在！", row.ButtonName, row.ButtonLink));
                    }
                    else
                    {
                        var button = new Button();
                        button.InjectFrom<NotNullInjection>(row);
                        db.Button.Add(button);
                    }
                }
                //批量更新
                foreach (var row in bulks.UpdatedRows)
                {
                    var button = await db.Button.FindAsync(row.Id);
                    button.InjectFrom(new NotNullInjection(), row);
                }

                //删除
                var deleteArray = bulks.DeletedRows.Where(row => row.Id != null).Select(s => s.Id).ToArray();
                if (deleteArray.Length > 0)
                {
                    await db.Button.Where(s => deleteArray.Contains(s.Id)).DeleteAsync();
                }

                await db.SaveChangesAsync();

                return new OperationResult<Button>() { success = true, message = bulks.DeletedRows.Count > 0 ? "数据已经成功删除！" : exists.Count > 0 ? String.Join("<br />", exists) : "保存成功！" };
            }
        }

        public OperationResult SaveRoleButtons(Guid id, BulkKeyDto<Guid> dto)
        {
            using (var db = new Db())
            {
                db.RolePermission.Where(s => s.RoleId == id).Delete();

                db.SaveChanges();

                foreach (var menuId in dto.KeyList)
                {
                    if(menuId != Guid.Empty) db.RolePermission.Add(new RolePermission { MenuId=menuId, RoleId=id });
                }

                db.SaveChanges();

                return new OperationResult() { success=true };
            }
        }

        public OperationResult SaveUserButtons(Guid id, BulkKeyDto<Guid> dto)
        {
            using (var db = new Db())
            {
                var allPermissions = GetAllMenuByUserId(id);
                db.UserPermission.Where(s => s.UserId == id).Delete();

                db.SaveChanges();

                foreach (var menuId in dto.KeyList)
                {
                    if (menuId != Guid.Empty && allPermissions.Count(s=>s.Id == menuId) == 0) db.UserPermission.Add(new UserPermission { MenuId = menuId, UserId = id });
                }

                db.SaveChanges();

                return new OperationResult() { success = true };
            }
        }

        public async Task<OperationResult<Role>> SaveRoles(BulkDto<RoleDto> bulks)
        {
            using (var db = new Db())
            {
                var exists = new List<string>();
                foreach (var row in bulks.InsertedRows)
                {
                    if (await db.Role.CountAsync(r => r.RoleName == row.RoleName) > 0)
                    {
                        exists.Add(string.Format("名为【{0}】的角色已经存在！", row.RoleName));
                    }
                    else
                    {
                        var role = new Role();
                        role.InjectFrom<NotNullInjection>(row);
                        db.Role.Add(role);
                    }
                }
                foreach (var row in bulks.UpdatedRows)
                {
                    var role = await db.Role.FindAsync(row.Id);
                    role.InjectFrom(new NotNullInjection(), row);
                    role.LastModificationTime = DateTime.Now;
                }

                //删除
                var deleteArray = bulks.DeletedRows.Where(row => row.Id != null).Select(s => s.Id).ToArray();
                if (deleteArray.Length > 0)
                {
                    await db.Role.Where(s => deleteArray.Contains(s.Id)).DeleteAsync();
                }

                await db.SaveChangesAsync();

                return new OperationResult<Role>() { success = true, message = bulks.DeletedRows.Count > 0 ? "数据已经成功删除！" : exists.Count > 0 ? String.Join("<br />", exists) : "保存成功！" };
            }
        }

        public async Task<OperationResult<Setting>> SaveSettings(BulkDto<SettingDto> bulks)
        {
            using (var db = new Db()) {
                var exists = new List<string>();
                foreach (var row in bulks.InsertedRows)
                {
                    if (await db.Setting.CountAsync(s => s.Key == row.Key) >
                        0)
                    {
                        exists.Add(string.Format("Key为【{0}】的参数已经存在！", row.Key));
                    }
                    else
                    {
                        var setting = new Setting();
                        setting.InjectFrom<NotNullInjection>(row);
                        db.Setting.Add(setting);
                    }
                }
                foreach (var row in bulks.UpdatedRows)
                {
                    var setting = await db.Setting.FindAsync(row.Id);
                    setting.InjectFrom(new NotNullInjection(), row);
                }
                //删除
                var deleteArray = bulks.DeletedRows.Where(row => row.Id != null).Select(s => s.Id).ToArray();
                if (deleteArray.Length > 0)
                {
                    await db.Setting.Where(s => deleteArray.Contains(s.Id)).DeleteAsync();
                }

                await db.SaveChangesAsync();

                return new OperationResult<Setting>() { success = true,message= bulks.DeletedRows.Count > 0 ? "数据已经成功删除！" : exists.Count > 0 ? String.Join("<br />", exists) : "保存成功！" };
            }
        }

        public List<MenuPermission> GetAllMenuByUserId(Guid userId)
        {
            using (var db = new Db()) 
            {
                var user = db.User.Include("Roles").SingleOrDefault(u => u.Id == userId);
                if (user == null) return null;

                var data = new List<MenuPermission>();
                foreach (var role in user.Roles)
                {
                    var rolePermissions = db.RolePermission.Where(s => s.RoleId == role.Id).ToList();
                    foreach (var menu in rolePermissions)
                    {
                        var menuPermission = db.MenuPermission.Find(menu.MenuId);
                        if (menuPermission != null && data.Count(s=>s.Id == menu.MenuId) == 0) data.Add(menuPermission);
                    }
                }

                var userPermissions = db.UserPermission.Where(s => s.UserId == userId).ToList();
                foreach (var menu in userPermissions)
                {
                    var menuPermission = db.MenuPermission.Find(menu.MenuId);
                    if (menuPermission != null && data.Count(s => s.Id == menu.MenuId) == 0) data.Add(menuPermission);
                }

                return data;
            }
        }

        public async Task<OperationResult> SaveMenuButtons(Guid id, BulkKeyDto<Guid> dto)
        {
            using (var db = new Db())
            {
                var menu = await db.MenuPermission.FindAsync(id);
                if (menu == null)
                {
                    return new OperationResult() { success = false, message = "Not found!" };
                }

                await db.MenuPermission.Where(m => m.ParentId == id && m.MenuType == "button" && m.AutoCreated).DeleteAsync();
                foreach (var button in db.Button.Where(p => dto.KeyList.Contains(p.Id)))
                {
                    db.MenuPermission.Add(new MenuPermission
                    {
                        MenuText = button.ButtonName,
                        MenuLink = button.ButtonLink,
                        MenuType = "button",
                        IconCls = button.IconCls,
                        IsActivated = "on",
                        AutoCreated = true,
                        ParentId = id
                    });
                }

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public List<CalendarEvent> GetCalendarEvents(DateTime start, DateTime end)
        {
            using (var db = new Db())
            {
                return db.CalendarEvent.Where(c => c.User.Id == AppSession.UserId && c.StartDate >= start && c.EndDate <= end)
                    .ToList();
            }
        }

        public async Task<OperationResult> UpdateCalendarEvent(Guid id, CalendarEventDto dto)
        {
            using (var db = new Db())
            {
                var user = new CurrentSession();

                var calendarEvent = await db.CalendarEvent.FindAsync(id);
                if (calendarEvent == null)
                {
                    return new OperationResult() { success = false, message = "Not found!" };
                }

                calendarEvent.InjectFrom(dto);
                calendarEvent.Subject = dto.Title;

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public async Task<OperationResult> CreateCalendarEvent(CalendarEventDto dto)
        {
            using (var db = new Db())
            {
                var calendarEvent = new CalendarEvent();
                calendarEvent.InjectFrom(dto);
                calendarEvent.User = await db.User.FindAsync(AppSession.UserId);
                calendarEvent.Subject = dto.Title;

                db.CalendarEvent.Add(calendarEvent);

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public List<MenuPermission> GetAllMenuByUser()
        {
            return GetAllMenuByUserId(AppSession.UserId.Value);
        }

        public async Task<Role> GetRoleByNameAsync(string roleName)
        {
            using (var db = new Db())
            {
                return await db.Role.SingleOrDefaultAsync(s => s.RoleName == roleName);
            }
        }

        public async Task DeleteCalendarEventAsync(Guid id)
        {
            using (var db = new Db())
            {
                await db.CalendarEvent.Where(s => s.Id == id).DeleteAsync();
            }
        }

        public async Task DeleteMenuAsync(Guid id)
        {
            using (var db = new Db())
            {
                await db.MenuPermission.Where(s => s.Id == id).DeleteAsync();
            }
        }

        public Role GetRoleByName(string roleName)
        {
            using (var db = new Db())
            {
                return db.Role.SingleOrDefault(s => s.RoleName == roleName);
            }
        }
    }
}
